import { addUploadedProjectToDb, queryAllProject } from "@/api/projectApi";
import { constObjs } from "@/const/const";
import {
  IncomeStream,
  LandingAgency,
  OutlayStream,
  Partners,
  Project
} from "@/interface/entity";
import { TablePattern } from "@/interface/general";
import store from "@/store";
import { ElMessage } from "element-plus";
import XLSX from "yxg-xlsx-style";
import { processUploadedProject } from "../functions/project";
import { CodeToText } from "element-china-area-data";

// sort functions
export const sortByCreatedDate = (a: Project, b: Project) => {
  if (a.createdDate == undefined || b.createdDate == undefined) {
    return -1;
  }
  if (new Date(a.createdDate) > new Date(b.createdDate)) {
    return 1;
  } else {
    return -1;
  }
};
// this function is used to convert a Date proporty(date|string  type) of a form to a string!
export const myDateFormat = (arg1: Date | string | undefined): string => {
  // 这里必须用参数arg去new一个Date出来，不然会提示.xxx is not a function！！
  if (arg1 == undefined) {
    return " ";
  }
  if (arg1 != null && arg1 != "" && arg1 != undefined) {
    return new Date(arg1 as Date).toLocaleDateString().replace(/(\/)/g, "-");
  } else {
    return "";
  }
};

// to currency format
export const numberToThousands = (num: number): string => {
  try {
    const parts = num.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    let res = parts.join(".");
    // Two decimal places
    if (parts[1] == null || parts[1] == undefined) {
      res += ".00";
    } else if (parts[1] != undefined && parts[1].length == 1) {
      res += "0";
    }

    return "￥" + res;
  } catch (error) {
    console.log(error);
    return "error";
  }
};
export const thousandsToNumber = (str: string): number => {
  if (str[0] == "￥") {
    str.slice(1);
    // console.log(str);
  }
  const parts = str.split(",");
  return parseFloat(parts.join(""));
};

export const percentageToNumber = (str: string): number => {
  return parseFloat(str.split("%").join(""));
};

// format the data to be shown
export const numberFormater = (
  val: number | string,
  valType: string
): string => {
  switch (valType) {
    case "%": {
      return val.toString().concat("%");
    }
    case "currency": {
      return numberToThousands(val as number);
    }
    // todo selectedarea
    case "selectedArea": {
      const area = (val as string).split(" ");
      const res = [] as string[];
      area.forEach(a => {
        res.push(CodeToText[a]);
      });
      return res.join("");
    }
  }
  return val as string;
};
// format the multi item's label
export const labelFormatter = (
  insertIndex: number,
  label: string,
  insertStr: string,
  type?: string
): string => {
  // if other
  if (type == "multi" || type == "form-item-list") {
    const labelArr = label.split("");
    labelArr.splice(insertIndex, 0, insertStr);
    return labelArr.join("");
  } else {
    // do nothing
    return label;
  }
};

//
export const getFormattedTime = (mode = "") => {
  const today = new Date();
  const y = today.getFullYear();
  // JavaScript months are 0-based.
  const m = today.getMonth() + 1;
  const d = today.getDate();
  const h = today.getHours();
  const mi = today.getMinutes();
  const s = today.getSeconds();
  let w = "";
  switch (today.getDay()) {
    case 0: {
      w = "星期日";
      break;
    }
    case 1: {
      w = "星期一";
      break;
    }
    case 2: {
      w = "星期二";
      break;
    }
    case 3: {
      w = "星期三";
      break;
    }
    case 4: {
      w = "星期四";
      break;
    }
    case 5: {
      w = "星期五";
      break;
    }
    case 6: {
      w = "星期六";
      break;
    }
  }
  if (mode == "nowtime") {
    return y + "年" + m + "月" + d + "日" + "," + w;
  }
  return y + "-" + m + "-" + d + "-" + h + "-" + mi + "-" + s;
};

// 对象数组去重
export function uniqueArr<T extends object>(
  arr: Array<T>,
  key: string
): Array<T> {
  const map = new Map();
  // 空数组
  if (arr.length == 0) {
    return arr;
  }
  // 检查key是否属于该对象
  Object.keys(arr[0]).forEach(k => {
    if (arr[0][k as keyof object] == undefined) {
      console.log(`${key}不是当前对象的属性！`);
      return arr;
    } else {
      arr.forEach(item => {
        if (!map.has(item[key as keyof object])) {
          map.set(item[key as keyof object], item);
        }
      });
    }
  });
  return [...map.values()];
}

// ------------upload------------------
// 生成excel文件
export function saveAs(obj: Blob, fileName: string) {
  if (obj == undefined || obj.size == 0 || obj.size == undefined) {
    return;
  }
  const tmpa = document.createElement("a");
  tmpa.download = fileName || "下载";
  tmpa.href = URL.createObjectURL(obj);
  tmpa.click();
  setTimeout(function() {
    URL.revokeObjectURL(tmpa.href);
  }, 100);
}

// export to excel
export const exportToExcel = (
  tableCols: TablePattern[],
  tableData: object[]
) => {
  import("@/const/excel").then(excel => {
    const title = ["表"];
    // 表头（一维数组）
    const tableHead = [] as string[];
    // 表头字段
    const propList = [] as string[];

    console.log("tableCOl", tableCols);

    // props.tableCol is a object array
    // todo filter by whether isshow
    tableCols.forEach(item => {
      if (item.type == "multi") {
        // maxLengthIndex will not be undefined when type == 'multi'
        //
        const maxLengthIndex = item.maxSubItemNum as number;
        const insertIndex = item.insertIndex as number;
        // 生成表头和proplist
        for (let i = 1; i <= maxLengthIndex; i++) {
          item?.subTitle?.forEach(subItem => {
            if (subItem.isShow) {
              tableHead.push(
                labelFormatter(
                  insertIndex,
                  subItem.label as string,
                  i.toString(),
                  item.type
                )
              );
              // 这里的multi e.g = landingAgencies.0.agencyName
              propList.push(
                `${item.prop}.${i - 1}.${subItem.prop}.${subItem.formatType}`
              );
            }
          });
        }
      } else {
        if (item.isShow) {
          tableHead.push(item.label as string);
          // e.g schoolManageRadio.%
          propList.push(`${item.prop}.${item.formatType}`);
        }
      }
    });

    console.log("tableHead", tableHead, "propList", propList);
    console.log("tableData", tableData);

    // props.tableData is a OBJECT ARRAY
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    // todo change
    const data = [] as any[][];
    tableData.forEach(tableDataItem => {
      const rowList = [] as any[];
      propList.forEach(list => {
        const listStr = list.split(".");
        try {
          if (listStr.length > 2) {
            // console.log(listStr);
            // e.g tableData[0].landingAgencies.0.shareRadio.%
            rowList.push(
              // listStr[3] can be "currency" or "%"
              numberFormater(
                tableDataItem[listStr[0] as keyof object][parseInt(listStr[1])][
                  listStr[2] as keyof object
                ],
                listStr[3]
              )
            );
          } else {
            rowList.push(
              numberFormater(
                tableDataItem[listStr[0] as keyof object],
                listStr[1]
              )
            );
          }
        } catch (error) {
          // e.g landingAgencies = {}
          rowList.push(" ");
        }
      });
      data.push(rowList);
    });
    console.log("data", data);

    const merges = [] as string[];
    excel.export_json_to_excel({
      title: title,
      header: tableHead,
      data,
      merges,
      filename: getFormattedTime(),
      autoWidth: true,
      bookType: "xlsx"
    });
  });
};

// before upload data
export const beforeUpload = (
  file: object,
  fileNamePattern: RegExp
): boolean => {
  console.log(file, fileNamePattern);
  const fileName = (file["name" as keyof object] as string).toLowerCase();
  // check filename
  if (fileName.length == 0) {
    ElMessage.error("文件名非法，请重新上传！");
    return false;
  }
  if (fileNamePattern.test(fileName.split(".")[1])) {
    return true;
  }
  return false;
};

// after the data is successfully uploaded
export async function processUploadedExcel<
  T extends Project | IncomeStream | OutlayStream
>(datas: T[]) {
  console.log("sheetdata", datas);
  const datasToDb = [] as T[];

  // 遍历datas生成datasToDb
  datas.forEach(data => {
    const agencies = [] as LandingAgency[];
    const partners = [] as Partners[];

    let dataItem = {} as T;

    switch (store.state.nowSystem) {
      case "project": {
        dataItem = JSON.parse(JSON.stringify(constObjs.projectForm));
        console.log(dataItem);
        break;
      }
    }
    // 遍历data的key
    Object.keys(data).forEach(key => {
      // 生成该行数据的落地机构和技术合作方列表（如果有）
      if (key[0] == "落" || key[0] == "技") {
        // 第几个落地机构|技术合作方
        const nowNum = key[0] == "落" ? key[4] : key[5];
        const keyWithoutNum = key.split(nowNum).join("");
        // 如agencyname shareradio
        const prop =
          constObjs.incomeStreamLabelPropMap[keyWithoutNum as keyof object];

        console.log(parseInt(nowNum), agencies.length, agencies);

        if (key[0] == "落") {
          if (parseInt(nowNum) != agencies.length) {
            agencies.push({
              agencyName: "",
              shareRadio: 0,
              shareAmount: 0
              // rebateTime: ""
            });
          }
          agencies[agencies.length - 1][prop as keyof LandingAgency] =
            data[key as keyof object];
          // 合作方
        } else if (key[0] == "技") {
          if (parseInt(nowNum) != partners.length) {
            // add a default parter
            partners.push({
              partnerName: "",
              shareRadio: 0,
              shareAmount: 0,
              caculation: "比例",
              partnerType: ""
            });
          }
          partners[partners.length - 1][prop as keyof Partners] =
            data[key as keyof object];
        }
      }

      // todo fixbug

      // 给dataItem里面的prop赋值（不包括落地机构和技术合作方）
      let prop = "";
      switch (store.state.nowSystem) {
        case "project": {
          prop = constObjs.projectLabelPropMap[key as keyof object] as string;
          break;
        }
        case "incomestream": {
          prop = constObjs.incomeStreamLabelPropMap[
            key as keyof object
          ] as string;
          break;
        }
        case "outlaystream": {
          prop = constObjs.outlayStreamLabelPropMap[
            key as keyof object
          ] as string;
          break;
        }
      }
      // 赋值
      if (key[0] != "落" && key[0] != "技") {
        dataItem[prop as keyof T] = data[key as keyof object];
      }
    });

    // 遍历完了，赋值落地机构和合作方（支出流水的话不用）.然后生成一行要存到db的数据
    switch (store.state.nowSystem) {
      case "project": {
        const tmp = dataItem as Project;
        tmp.landingAgencies = agencies.filter(
          agency => agency.agencyName.length > 1
        );
        tmp.partners = partners.filter(parter => parter.partnerName.length > 1);
        (datasToDb as Project[]).push(tmp);
        break;
      }
      case "incomestream": {
        const tmp = dataItem as IncomeStream;
        tmp.landingAgencies = agencies.filter(
          agency => agency.agencyName.length > 1
        );
        tmp.partners = partners.filter(parter => parter.partnerName.length > 1);
        (datasToDb as IncomeStream[]).push(tmp);
        break;
      }
      case "outlaystream": {
        const tmp = dataItem as OutlayStream;
        (datasToDb as OutlayStream[]).push(tmp);
        break;
      }
    }
  });

  console.log("datasToDb", datasToDb);

  switch (store.state.nowSystem) {
    case "project": {
      await addUploadedProjectToDb(
        processUploadedProject(datasToDb as Project[])
      );
      queryAllProject();
      break;
    }
  }
}

// 覆盖默认的上传行为，可以自定义上传的实现,params为默认参数
export const uploadExcel = (params: object) => {
  // console.log("params", params);
  try {
    // get the file object
    const file = params["file" as keyof object];

    const fileReader = new FileReader();
    // 当使用fileReader.readAsBinaryString时执行
    fileReader.onload = ev => {
      try {
        if (ev.target != null) {
          const data = ev.target.result;

          const workbook = XLSX.read(data, {
            type: "binary"
          });

          const wsname1 = workbook.SheetNames[0]; //取第一张表

          const ws1 = XLSX.utils.sheet_to_json(workbook.Sheets[wsname1]); //生成第一张表的json表格内容
          console.log("ws1", ws1);

          processUploadedExcel(ws1);
        } else {
          console.log("ev.target", ev.target);
        }
      } catch (e) {
        console.log(e);
        return;
      }
    };
    // params is typeof File
    fileReader.readAsBinaryString(file);
  } catch (error) {
    console.log(error);
  }
};
